﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Threading;
using OnlineGameLibrary.MessageEx;
using OnlineGameLibrary.ClientChannel;

namespace OnlineGameLibrary.Contract
{
    public partial class Player//:IMyClientChannel
    {
        private IGameRoomServiceCallBack _callbackchannel;

        public Player(IGameRoomServiceCallBack callback)
        {
            _callbackchannel = callback;
        }

        bool _iswaitingmsg = false;
        Message _currentmsg = null;

        AutoResetEvent _are = new AutoResetEvent(false);
        object _fetchmsglock = new object();
        object _setmsglock = new object();

        //public bool ReceiveMessageFromPlayer(TimeSpan waitingtime, out Message msg)
        //{
        //    lock (_fetchmsglock)
        //    {
        //        _iswaitingmsg = true;
        //        Console.WriteLine("set to true,player :" + this.PlayerID);
        //        var result = _are.WaitOne(waitingtime);
        //        _iswaitingmsg = false;
        //        Console.WriteLine("set to false");

        //        msg = _currentmsg;

        //        if (result)
        //            return true;
        //        else
        //            return false;
        //    }
        //}

        //public bool ReceiveMessageFromPlayer(TimeSpan waitingtime, MessageDefine msgdef, out MessageContent msgcontent)
        //{
        //    Message msg;
        //    var result = ReceiveMessageFromPlayer(waitingtime, out msg);
        //    if (result && msgdef.Action == msg.GetAction())
        //    {
        //        msgcontent = msgdef.GetMessage(msg);
        //        return true;
        //    }
        //    else
        //    {
        //        msgcontent = null;
        //        return false;
        //    }
        //}

        //// for service to call
        //public bool ReceiveMessageFormService(Message msg)
        //{
        //    lock (_setmsglock)
        //    {
        //        if (_iswaitingmsg)
        //        {
        //            var buffer = msg.CreateBufferedCopy(1);
        //            _currentmsg = buffer.CreateMessage();
        //            _are.Set();
        //            return true;
        //        }
        //        else
        //        {
        //            Console.WriteLine("failed reponse, player :" + this.PlayerID);
        //            return false;
        //        }
        //    }
        //}

        public bool SendMessageToPlayer(Message msg)
        {
            if (_callbackchannel != null)
            {
                if (((ICommunicationObject)_callbackchannel).State
                    == CommunicationState.Opened)
                {
                    try
                    {
                        _callbackchannel.SendGameMessage(msg);
                        return true;
                    }
                    catch
                    {
                        _callbackchannel = null;
                        this.PlayerState = PlayerState.Leave;
                    }
                }
                else
                {
                    _callbackchannel = null;
                    this.PlayerState = PlayerState.Leave;
                }
            }
            return false;
        }

        public bool ReceiveMessageFromPlayer(TimeSpan waitingtime, MessageDefine msgdef, out MessageContent msgcontent)
        {
            AutoResetEvent are = new AutoResetEvent(false);
            var mar = BeginReceiveMessageFromPlayer(msgdef,
                new AsyncCallback(
                    (ar) =>
                    {
                        are.Set();
                    }), null);
            are.WaitOne(waitingtime);

            if (mar.IsCompleted)
            {
                msgcontent = EndReceiveMessageFromPlayer(mar);
                return true;
            }
            else
            {
                CancelReceiveMessageFromPlayer(mar);
                msgcontent = null;
                return false;
            }
        }

        public bool ReceiveMessageFormService(Message msg)
        {
            var action = msg.GetAction();
            if (_asyncdict.ContainsKey(action))
            {
                var asynpack = _asyncdict[action];
                _asyncdict.Remove(action);

                asynpack.AsyncResult.MessageContent = asynpack.AsyncResult.MessageDefine.GetMessage(msg);
                asynpack.AsyncResult.IsCompleted = true;
                asynpack.AsyncCallback.BeginInvoke(asynpack.AsyncResult, null, null);
                return true;
            }
            else
                return false;
        }

        Dictionary<string, AsyncPack> _asyncdict = new Dictionary<string, AsyncPack>();
        public IAsyncResult BeginReceiveMessageFromPlayer(MessageDefine define, AsyncCallback callback, object asyncState)
        {
            lock (_asyncdict)
            {
                if (_asyncdict.ContainsKey(define.Action))
                    throw new Exception("duplicated message receive registration. action:" + define.Action);

                var ar = new MyAsyncResult(asyncState, define);

                _asyncdict.Add(define.Action, new AsyncPack(ar, callback));
                return ar;
            }
        }

        public MessageContent EndReceiveMessageFromPlayer(IAsyncResult ar)
        {
            var myar = ar as MyAsyncResult;
            return myar.MessageContent;
        }

        public void CancelReceiveMessageFromPlayer(IAsyncResult ar)
        {
            lock (_asyncdict)
            {
                var pair = _asyncdict.FirstOrDefault(p => p.Value.AsyncResult == ar);
                _asyncdict.Remove(pair.Key);
            }
        }
    }
}
